package com.cqq.common.core.util;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * <h3>Map 构建类</h3>
 * 
 * <p>使用链式方式进行Map的快速构建, 非线程安全</p>
 * <pre class="code">MapBuilder.put("id", id).and("pageSize", pageSize).and("offset", offset).build();</pre>
 * 
 * @author GUOQIANG
 * @version 1.0.0
 */
public class MapBuilder<K, V> {

	private Map<K, V> map;

	private MapBuilder() {
		map = newLinkedHashMap();
	}

	/**
	 * <h3>添加一个对键值数据(指定map值为Object), 开启builder链式编程的方法</h3>
	 * 
	 * @param <K> key类型
	 * @param key 被添加的数据关键字
	 * @param value 被添加的数据值
	 * @return MapBuilder
	 */
	public static <K> MapBuilder<K, Object> putObj(K key, Object value) {
		return new MapBuilder<K, Object>().and(key, value);
	}

	/**
	 * <h3>添加一个对键值数据, 开启builder链式编程的方法</h3>
	 * 
	 * @param <K> key类型
	 * @param key 被添加的数据关键字
	 * @param <V> value类型
	 * @param value 被添加的数据值
	 * @return MapBuilder
	 */
	public static <K, V> MapBuilder<K, V> put(K key, V value) {
		return new MapBuilder<K, V>().and(key, value);
	}

	/**
	 * <h3>添加一个对键值数据</h3>
	 * 
	 * @param key 被添加的数据关键字
	 * @param value 被添加的数据值
	 * @return MapBuilder
	 */
	public MapBuilder<K, V> and(K key, V value) {
		map.put(key, value);
		return this;
	}

	/**
	 * <h3>添加一个对键值数据</h3>
	 * 
	 * @param key 被删除的数据关键字
	 * @return MapBuilder
	 */
	public MapBuilder<K, V> del(K key) {
		map.remove(key);
		return this;
	}

	/**
	 * <h3>删除一个或多个对键值数据</h3>
	 * 
	 * <p>所有值相同的键值对数据都将被删除</p>
	 * 
	 * @param value 被删除的数据值
	 * @return MapBuilder
	 */
	public MapBuilder<K, V> delByValue(V value) {
		if (!map.containsValue(value)) {
			return this;
		}
		List<K> keys = ListBuilder.newArrayList();
		Set<Entry<K, V>> entrySet = map.entrySet();
		for (Entry<K, V> entry : entrySet) {
			if (entry.getValue().equals(value)) {
				keys.add(entry.getKey());
			}
		}
		for (K key : keys) {
			map.remove(key);
		}
		return this;
	}

	/**
	 * <h3>生成map对象</h3>
	 * 
	 * @return map
	 */
	public Map<K, V> build() {
		return map;
	}

	public static <K, V> Map<K, V> newHashMap() {
		return new HashMap<K, V>();
	}

	public static <K, V> Map<K, V> newLinkedHashMap() {
		return new LinkedHashMap<K, V>();
	}
}